package com.atguigu.lease.web.app.service.impl;


import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;

import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.app.service.LoginService;
import com.atguigu.lease.web.app.service.UserInfoService;
import com.atguigu.lease.web.app.vo.user.LoginVo;
import com.atguigu.lease.web.app.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private Client client;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserInfoService userInfoService;

    /**
     * @author gengjian
     * @date 2024/12/14 15:09:50
     * 获取短信验证码
     */
    @Override
    public void getCode(String phone) {
        //先判断手机号是否为空
        if (ObjectUtils.isEmpty(phone)){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        //计算短信发送的间隔是否超出指定时间1分钟
        //前缀+手机号为redis的key
        //验证码为value 存redis为了后续做验证码校验
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;
        //检查有没有未过期的验证码 键在值在剑亡人亡
        Boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey){
            //检查短信发送间隔是否大于一分钟
            //获取剩余时间
            Long expire = redisTemplate.getExpire(key,TimeUnit.SECONDS);
            //有效时间600-剩余时间 < 间隔时间60 则抛出发送频繁异常
            if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire < RedisConstant.APP_LOGIN_CAPTCHA_TTL_SEC){
                throw new LeaseException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
            }
        }
        //生成短信验证码（6位数字）
//        Random random = new Random();
//        int smsCaptcha = 100000 + random.nextInt(900000);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            Random random = new Random();
            int number = random.nextInt(10);
            sb.append(number);
        }

        // 构造请求对象，请填入请求参数值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName("阿里云短信测试")
                .setTemplateCode("SMS_154950909")
                .setTemplateParam("{\"code\":\"" + sb.toString() + "\"}\n");
        //存储到redis
        redisTemplate.opsForValue().set(key,sb.toString(),RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
        //发送短信
        try {
            client.sendSms(sendSmsRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @author gengjian
     * @date 2024/12/15 14:02:40
     * 登录功能
     */
    @Override
    public String login(LoginVo loginVo) {
        //校验手机号和验证码是否为空
        if (ObjectUtils.isEmpty(loginVo.getPhone())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        if (ObjectUtils.isEmpty(loginVo.getCode())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }
        //校验验证码 验证码正确说明手机也没问题
        String key = RedisConstant.APP_LOGIN_PREFIX + loginVo.getPhone();
        String value = (String) redisTemplate.opsForValue().get(key);
        //如果验证码不存在则说明过期
        if (ObjectUtils.isEmpty(value)){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }
        //不相等则输入错误
        if (!value.equals(loginVo.getCode())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }
        //判断手机号是否已存在，存在则登录，不存在则注册
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getPhone,loginVo.getPhone());
        UserInfo userInfo = userInfoService.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(userInfo)){
            //注册
            userInfo = new UserInfo();
            //默认昵称
            userInfo.setNickname("佚名"+loginVo.getPhone().substring(5));
            userInfo.setStatus(BaseStatus.ENABLE);
            userInfo.setPhone(loginVo.getPhone());
            userInfoService.save(userInfo);
        }
        //判断用户是否被禁用
        if (userInfo.getStatus().equals(BaseStatus.DISABLE)){
            throw new LeaseException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
        }
        //生成token返回给前端
        return JwtUtil.createToken(userInfo.getId(),userInfo.getPhone());
    }

    /**
     * @author gengjian
     * @date 2024/12/15 15:48:19
     * 获取用户信息
     */
    @Override
    public UserInfoVo info(String token) {
        //解析token
        Claims claims = JwtUtil.parseToken(token);
        //解析出来的是integer类型 转不了long
        Integer userId = (Integer) claims.get("userId");
        UserInfo userinfo = userInfoService.getById(userId);
        return new UserInfoVo(userinfo.getNickname(),userinfo.getAvatarUrl());
    }
}
